Use O_CLOEXEC to avoid race conditions#10162
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Hardens file-descriptor creation against FD leaks across fork()+exec() in multithreaded programs by using close-on-exec flags (e.g., O_CLOEXEC, SOCK_CLOEXEC, EFD_CLOEXEC) at creation time where possible.
Changes:
- Introduces portable
WC_*_CLOEXECmacros that fall back to no-ops on unsupported platforms. - Applies
WC_CLOEXEC/WC_SOCK_CLOEXEC/WC_EFD_CLOEXECto variousopen(),socket(), andeventfd()call sites. - Uses
accept4(..., SOCK_CLOEXEC)for AF_ALG where available and passes close-on-exec flag toperf_event_open.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfssl/wolfcrypt/wc_port.h | Adds portable close-on-exec flag macros for FD-creating syscalls. |
| wolfcrypt/src/random.c | Opens RNG-related device FDs with O_CLOEXEC where available. |
| wolfcrypt/src/port/intel/quickassist_mem.c | Opens QAT memory device with O_CLOEXEC. |
| wolfcrypt/src/port/devcrypto/wc_devcrypto.c | Opens /dev/crypto with O_CLOEXEC. |
| wolfcrypt/src/port/caam/wolfcaam_qnx.c | Opens CAAM device with O_CLOEXEC. |
| wolfcrypt/src/port/af_alg/wc_afalg.c | Uses accept4(..., SOCK_CLOEXEC) when available; creates AF_ALG sockets with SOCK_CLOEXEC. |
| wolfcrypt/src/port/af_alg/afalg_hash.c | Uses accept4(..., SOCK_CLOEXEC) when available for duplicated AF_ALG FDs. |
| wolfcrypt/benchmark/benchmark.c | Adds PERF_FLAG_FD_CLOEXEC to perf_event_open flags. |
| src/wolfio.c | Creates TCP sockets with SOCK_CLOEXEC; sets FD_CLOEXEC after accept(). |
| src/ssl.c | Creates EGD AF_UNIX socket with SOCK_CLOEXEC. |
| src/crl.c | Uses CLOEXEC flags for eventfd/inotify/open() in CRL monitor paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dgarske
left a comment
There was a problem hiding this comment.
🐺 Skoll Code Review
Overall recommendation: REQUEST_CHANGES
Findings: 5 total — 4 posted, 1 skipped
Posted findings
- [Low] crl.c kqueue path: F_SETFD without read-modify-write —
src/crl.c:1719 - [Low] wolfio.c: defined(SOCK_CLOEXEC) guard in accept4 path is tautologically true —
src/wolfio.c:1642-1643 - [Medium] afalg_hash.c: accept4 used without _GNU_SOURCE but guarded by system SOCK_CLOEXEC —
wolfcrypt/src/port/af_alg/afalg_hash.c:226-232 - [High] wolfio.c: _GNU_SOURCE placement may conflict if libwolfssl_sources.h pulls in system headers —
src/wolfio.c:31-36
Skipped findings
- [Medium] wc_afalg.c: SOCK_CLOEXEC fallback defeats accept4 guard — missing _GNU_SOURCE
Review generated by Skoll via openclaw
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #10162
Scan targets checked: wolfcrypt-api_misuse, wolfcrypt-bugs, wolfcrypt-compliance, wolfcrypt-concurrency, wolfcrypt-consttime, wolfcrypt-defaults, wolfcrypt-mutation, wolfcrypt-port, wolfcrypt-port-bugs, wolfcrypt-portability, wolfcrypt-proptest, wolfcrypt-src, wolfcrypt-zeroize, wolfssl-bugs, wolfssl-compliance, wolfssl-consttime, wolfssl-defaults, wolfssl-mutation, wolfssl-proptest, wolfssl-src, wolfssl-zeroize
Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #10162
Scan targets checked: wolfcrypt-api_misuse, wolfcrypt-bugs, wolfcrypt-compliance, wolfcrypt-concurrency, wolfcrypt-consttime, wolfcrypt-defaults, wolfcrypt-mutation, wolfcrypt-port, wolfcrypt-port-bugs, wolfcrypt-portability, wolfcrypt-proptest, wolfcrypt-src, wolfcrypt-zeroize, wolfssl-bugs, wolfssl-compliance, wolfssl-consttime, wolfssl-defaults, wolfssl-mutation, wolfssl-proptest, wolfssl-src, wolfssl-zeroize
No new issues found in the changed files. ✅
douzzer
left a comment
There was a problem hiding this comment.
Would be a lot cleaner+nicer to take the wc_open_cloexec() added in random.c, move it to wc_port.c, make it a WOLFSSL_LOCAL, and use it everywhere consistently.
While you're at it, it would make sense to add other syscall wrappers for calls used over and over with CLOEXEC -- probably accept(), probably others.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| WOLFSSL_LOCAL void wc_set_cloexec(int fd); | ||
| WOLFSSL_LOCAL int wc_open_cloexec(const char* path, int flags); | ||
| WOLFSSL_LOCAL int wc_socket_cloexec(int domain, int type, int protocol); | ||
| WOLFSSL_LOCAL int wc_accept_cloexec(int sockfd, void* addr, void* addrlen); | ||
| #else | ||
| /* Platforms without POSIX close-on-exec semantics (Windows, OS/2 OW, | ||
| * Linux kernel module, Zephyr, etc.): pass through to plain syscalls | ||
| * where the underlying headers are available in the caller. */ | ||
| #define wc_set_cloexec(fd) ((void)(fd)) | ||
| #define wc_open_cloexec(path, flags) open((path), (flags)) | ||
| #define wc_socket_cloexec(domain, type, protocol) \ | ||
| socket((domain), (type), (protocol)) | ||
| #define wc_accept_cloexec(sockfd, addr, addrlen) \ | ||
| accept((sockfd), (addr), (addrlen)) |
There was a problem hiding this comment.
wc_open_cloexec(const char* path, int flags) cannot correctly represent open() calls that require a third mode_t argument (e.g., when flags contains O_CREAT). Additionally, the non-POSIX passthrough macro always expands to a 2-argument open(path, flags). Consider changing wc_open_cloexec to accept an optional mode (e.g., a variadic interface that forwards mode when needed, or a separate wc_open_cloexec_mode(path, flags, mode)), so the helper is safe for all open() use cases.
| int wc_accept_cloexec(int sockfd, void* addr, void* addrlen) | ||
| { | ||
| int fd; | ||
| #if defined(__linux__) || defined(__ANDROID__) | ||
| fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen, | ||
| SOCK_CLOEXEC); | ||
| if (fd >= 0) | ||
| return fd; | ||
| if (errno != ENOSYS && errno != EINVAL) | ||
| return fd; | ||
| #endif | ||
| fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen); |
There was a problem hiding this comment.
Using void* for addr/addrlen removes type checking and forces casts at every callsite/implementation, which can hide real signature mismatches across platforms. Prefer a typed signature (e.g., struct sockaddr* and socklen_t* for the POSIX implementation) and, where Windows differs, provide a platform-specific overload via macro/inline wrapper using the platform socket-length type. This will also help prevent incorrect casts like the one currently needed in wolfio.c.
| int wc_accept_cloexec(int sockfd, void* addr, void* addrlen) | |
| { | |
| int fd; | |
| #if defined(__linux__) || defined(__ANDROID__) | |
| fd = accept4(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen, | |
| SOCK_CLOEXEC); | |
| if (fd >= 0) | |
| return fd; | |
| if (errno != ENOSYS && errno != EINVAL) | |
| return fd; | |
| #endif | |
| fd = accept(sockfd, (struct sockaddr*)addr, (socklen_t*)addrlen); | |
| int wc_accept_cloexec(int sockfd, struct sockaddr* addr, socklen_t* addrlen) | |
| { | |
| int fd; | |
| #if defined(__linux__) || defined(__ANDROID__) | |
| fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); | |
| if (fd >= 0) | |
| return fd; | |
| if (errno != ENOSYS && errno != EINVAL) | |
| return fd; | |
| #endif | |
| fd = accept(sockfd, addr, addrlen); |
Description
Use the "close-on-exec" flag at file creation time to harden multithread use cases against race conditions.
Fixes #9753
Testing
build testing
Checklist